package top.superflow.flow.config.parse.center

import java.io.{File, FilenameFilter}

import top.superflow.core.utils.PojoUtils
import top.superflow.exception.RequestUnsupportedException
import top.superflow.flow.config.Identifiable
import top.superflow.flow.config.parse.Parser
import top.superflow.flow.inner.InnerSpringContextResourceParser
import top.superflow.flow.load.FlowPathUtils
import top.superflow.json.util.JsonUtils
import top.superflow.lang.StringUtils
import top.superflow.log.Loggable

class ParserLoader private extends Loggable{

  private val parserFolder : String = FlowPathUtils.getResourcePath("parser")

  private final val PARSER_FILE_SUFFIX = "parser.json"

  private var dependencies : Map[String,Any] = _

  def init(dependencies: Map[String, Any]): Unit = {
    this.dependencies = dependencies
  }

  def load  {
    val parserRootFolder = new File(parserFolder)

    if(parserRootFolder.isDirectory()){
      parserRootFolder.listFiles(new FilenameFilter(){
        override def accept(dir: File, name: String): Boolean = name.endsWith(PARSER_FILE_SUFFIX)
      }).foreach(file => {
        val parserMapping= loadParser(file)
        registerParser(parserMapping)
      })
    }else{
      logger.error("The root folder [{}] of the flow is not correct, please correct it. Exit now.", parserFolder)
      System.exit(-1)
    }
  }

  private def loadParser(file : File) = {
    logger.info("Start to load parser mapping from file:[{}]", file)

    val parserMapping = JsonUtils.readJson(file)

    parserMapping
  }

  private def registerParser(parserMapping : Map[String, String]): Unit ={
    for((configParserkey , parser) <-  parserMapping){
      registerParser(configParserkey, parser)
    }
  }

  private def registerParser(configParserKey : String, fullClassPath : String): Unit ={
    if(StringUtils.isBlank(fullClassPath)){
      throw new RequestUnsupportedException("The parser class should not be black string!")
    }

    val parser = generateParser(fullClassPath)

    loadResourceForInnerParser(parser)

    GlobalParserCenter.getInstance.register(configParserKey, parser)
  }

  private def generateParser(fullClassPath : String ): Parser[_ <: Identifiable] ={
    val parser = PojoUtils.createInstance(fullClassPath)

    if(!parser.isInstanceOf[Parser[_ <: Identifiable]]){
      throw new RequestUnsupportedException("The class [" + fullClassPath + "] is not the sub class of [" + classOf[Parser[_ <: Identifiable]].getName + "], please make sure it's in the class path!")
    }

    parser.asInstanceOf[Parser[_ <: Identifiable]]
  }


  private def loadResourceForInnerParser(parser : Parser[_ <: Identifiable]): Unit ={
    if(parser == null){
      return
    }

    if(parser.isInstanceOf[InnerSpringContextResourceParser]){
      parser.asInstanceOf[InnerSpringContextResourceParser].setDependencies(this.dependencies)
    }
  }
}

object ParserLoader{

  private final val instance = new ParserLoader

  def getInstance = instance
}
